package com.caseprocessing.service;

import com.caseprocessing.model.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 * 增强型合规性检查器
 * 基于业务规则和法规标准实现细化的合规性检查
 */
public class EnhancedComplianceChecker extends ComplianceChecker {
    
    private Map<DocumentType, ComplianceRuleSet> typeSpecificRules;
    private LegalCitationValidator legalValidator;
    private AmountFormatValidator amountValidator;
    private ProcedureValidator procedureValidator;
    
    public EnhancedComplianceChecker() {
        super();
        this.typeSpecificRules = initializeTypeSpecificRules();
        this.legalValidator = new LegalCitationValidator();
        this.amountValidator = new AmountFormatValidator();
        this.procedureValidator = new ProcedureValidator();
    }
    
    /**
     * 增强型文档合规检查
     */
    @Override
    public ComplianceResult checkDocument(DocumentSegment document) {
        ComplianceResult result = super.checkDocument(document);
        
        // 执行类型特定的增强检查
        EnhancedComplianceResult enhancedResult = performEnhancedChecks(document);
        
        // 合并检查结果
        mergeResults(result, enhancedResult);
        
        return result;
    }
    
    /**
     * 执行增强型检查
     */
    private EnhancedComplianceResult performEnhancedChecks(DocumentSegment document) {
        EnhancedComplianceResult result = new EnhancedComplianceResult();
        DocumentType type = document.getDocumentType();
        
        switch (type) {
            case CASE_DECISION:
                result = checkDecisionDocument(document);
                break;
            case NOTIFICATION:
                result = checkNotificationDocument(document);
                break;
            case INVESTIGATION_RECORD:
                result = checkInvestigationRecord(document);
                break;
            case HEARING_RECORD:
                result = checkHearingRecord(document);
                break;
            case EVIDENCE_LIST:
                result = checkEvidenceList(document);
                break;
            default:
                result = performGeneralEnhancedChecks(document);
                break;
        }
        
        return result;
    }
    
    /**
     * 处罚决定书专项检查
     */
    private EnhancedComplianceResult checkDecisionDocument(DocumentSegment document) {
        EnhancedComplianceResult result = new EnhancedComplianceResult();
        String content = document.getFullText();
        List<String> issues = new ArrayList<>();
        
        // 1. 必要要素检查
        checkRequiredElements(content, getDecisionRequiredElements(), issues);
        
        // 2. 法条引用检查
        LegalCitationResult legalResult = legalValidator.validateLegalCitations(content);
        if (!legalResult.isValid()) {
            issues.addAll(legalResult.getIssues());
        }
        
        // 3. 金额格式检查
        AmountValidationResult amountResult = amountValidator.validateAmountFormat(content);
        if (!amountResult.isValid()) {
            issues.addAll(amountResult.getIssues());
        }
        
        // 4. 送达要求检查
        checkDeliveryRequirements(content, issues);
        
        // 5. 救济途径检查
        checkRemedyOptions(content, issues);
        
        // 6. 当事人信息完整性
        checkPartyInformation(content, issues);
        
        result.setIssues(issues);
        result.setStatus(issues.isEmpty() ? CheckStatus.PASSED : CheckStatus.FAILED);
        
        return result;
    }
    
    /**
     * 获取处罚决定书必要要素
     */
    private String[] getDecisionRequiredElements() {
        return new String[]{
            "当事人", "被处罚人", "违法事实", "违法行为", 
            "处罚依据", "法律依据", "处罚决定", "罚款",
            "执行方式", "履行期限", "救济途径", "复议", "诉讼",
            "送达", "生效"
        };
    }
    
    /**
     * 检查必要要素
     */
    private void checkRequiredElements(String content, String[] requiredElements, List<String> issues) {
        for (String element : requiredElements) {
            if (!content.contains(element)) {
                issues.add("缺少必要要素：" + element);
            }
        }
    }
    
    /**
     * 检查送达要求
     */
    private void checkDeliveryRequirements(String content, List<String> issues) {
        String[] deliveryKeywords = {"送达", "公告送达", "直接送达", "邮寄送达", "委托送达"};
        
        boolean hasDelivery = Arrays.stream(deliveryKeywords)
                .anyMatch(content::contains);
        
        if (!hasDelivery) {
            issues.add("缺少送达方式说明");
        }
        
        // 检查送达回证
        if (!content.contains("送达回证") && !content.contains("送达凭证")) {
            issues.add("缺少送达回证要求");
        }
    }
    
    /**
     * 检查救济途径
     */
    private void checkRemedyOptions(String content, List<String> issues) {
        boolean hasAdminReconsideration = content.contains("行政复议") || content.contains("复议");
        boolean hasLawsuit = content.contains("行政诉讼") || content.contains("起诉");
        
        if (!hasAdminReconsideration && !hasLawsuit) {
            issues.add("缺少救济途径说明（行政复议或行政诉讼）");
        }
        
        // 检查期限说明
        Pattern timePattern = Pattern.compile("(\\d+)日内");
        Matcher matcher = timePattern.matcher(content);
        
        if (!matcher.find()) {
            issues.add("缺少救济途径的期限说明");
        }
    }
    
    /**
     * 检查当事人信息
     */
    private void checkPartyInformation(String content, List<String> issues) {
        // 检查自然人信息要素
        if (content.contains("身份证") || content.contains("公民")) {
            checkNaturalPersonInfo(content, issues);
        }
        
        // 检查法人信息要素
        if (content.contains("法定代表人") || content.contains("统一社会信用代码")) {
            checkLegalPersonInfo(content, issues);
        }
        
        // 基本信息检查
        if (!content.contains("住址") && !content.contains("地址")) {
            issues.add("当事人缺少住址信息");
        }
    }
    
    /**
     * 检查自然人信息
     */
    private void checkNaturalPersonInfo(String content, List<String> issues) {
        if (!content.contains("身份证号") && !content.contains("身份证件号码")) {
            issues.add("自然人当事人缺少身份证件号码");
        }
        
        // 检查身份证号格式
        Pattern idPattern = Pattern.compile("\\d{17}[\\dXx]");
        if (!idPattern.matcher(content).find()) {
            issues.add("身份证号码格式可能不正确");
        }
    }
    
    /**
     * 检查法人信息
     */
    private void checkLegalPersonInfo(String content, List<String> issues) {
        if (!content.contains("统一社会信用代码") && !content.contains("组织机构代码")) {
            issues.add("法人当事人缺少统一社会信用代码");
        }
        
        if (!content.contains("法定代表人")) {
            issues.add("法人当事人缺少法定代表人信息");
        }
    }
    
    /**
     * 告知书专项检查
     */
    private EnhancedComplianceResult checkNotificationDocument(DocumentSegment document) {
        EnhancedComplianceResult result = new EnhancedComplianceResult();
        String content = document.getFullText();
        List<String> issues = new ArrayList<>();
        
        // 1. 告知内容完整性
        checkNotificationContent(content, issues);
        
        // 2. 期限要求
        checkNotificationTimeLimit(content, issues);
        
        // 3. 权利告知
        checkRightsNotification(content, issues);
        
        result.setIssues(issues);
        result.setStatus(issues.isEmpty() ? CheckStatus.PASSED : CheckStatus.WARNING);
        
        return result;
    }
    
    /**
     * 检查告知内容
     */
    private void checkNotificationContent(String content, List<String> issues) {
        String[] requiredContent = {
            "违法事实", "处罚依据", "拟处罚内容", "陈述权", "申辩权"
        };
        
        for (String item : requiredContent) {
            if (!content.contains(item)) {
                issues.add("告知书缺少：" + item);
            }
        }
    }
    
    /**
     * 检查告知期限
     */
    private void checkNotificationTimeLimit(String content, List<String> issues) {
        if (content.contains("听证")) {
            // 听证告知应有3日期限
            if (!content.contains("3日") && !content.contains("三日")) {
                issues.add("听证告知缺少3日期限要求");
            }
        }
    }
    
    /**
     * 检查权利告知
     */
    private void checkRightsNotification(String content, List<String> issues) {
        if (!content.contains("陈述") || !content.contains("申辩")) {
            issues.add("缺少陈述申辩权利告知");
        }
        
        if (content.contains("听证") && !content.contains("听证权")) {
            issues.add("涉及听证但缺少听证权利告知");
        }
    }
    
    /**
     * 调查笔录专项检查
     */
    private EnhancedComplianceResult checkInvestigationRecord(DocumentSegment document) {
        EnhancedComplianceResult result = new EnhancedComplianceResult();
        String content = document.getFullText();
        List<String> issues = new ArrayList<>();
        
        // 1. 基本格式检查
        checkRecordBasicFormat(content, issues);
        
        // 2. 人员信息检查
        checkRecordPersonnel(content, issues);
        
        // 3. 程序要求检查
        checkRecordProcedure(content, issues);
        
        result.setIssues(issues);
        result.setStatus(issues.isEmpty() ? CheckStatus.PASSED : CheckStatus.WARNING);
        
        return result;
    }
    
    /**
     * 检查笔录基本格式
     */
    private void checkRecordBasicFormat(String content, List<String> issues) {
        String[] basicElements = {"时间", "地点", "询问人", "记录人", "被询问人"};
        
        for (String element : basicElements) {
            if (!content.contains(element)) {
                issues.add("调查笔录缺少：" + element);
            }
        }
    }
    
    /**
     * 检查笔录人员信息
     */
    private void checkRecordPersonnel(String content, List<String> issues) {
        // 检查执法人员数量（至少2人）
        Pattern investigatorPattern = Pattern.compile("询问人[：:\\s]*([\\u4e00-\\u9fa5]+)[，、\\s]+([\\u4e00-\\u9fa5]+)");
        if (!investigatorPattern.matcher(content).find()) {
            issues.add("询问人员应至少2人");
        }
        
        // 检查证件出示
        if (!content.contains("出示证件") && !content.contains("执法证")) {
            issues.add("缺少执法证件出示记录");
        }
    }
    
    /**
     * 检查笔录程序
     */
    private void checkRecordProcedure(String content, List<String> issues) {
        // 检查权利告知
        if (!content.contains("权利义务") && !content.contains("如实回答")) {
            issues.add("缺少权利义务告知");
        }
        
        // 检查签名确认
        if (!content.contains("以上笔录") && !content.contains("确认无误")) {
            issues.add("缺少笔录确认环节");
        }
    }
    
    /**
     * 证据清单专项检查
     */
    private EnhancedComplianceResult checkEvidenceList(DocumentSegment document) {
        EnhancedComplianceResult result = new EnhancedComplianceResult();
        String content = document.getFullText();
        List<String> issues = new ArrayList<>();
        
        // 1. 清单格式检查
        checkEvidenceListFormat(content, issues);
        
        // 2. 证据编号检查
        checkEvidenceNumbering(content, issues);
        
        // 3. 证据描述检查
        checkEvidenceDescription(content, issues);
        
        result.setIssues(issues);
        result.setStatus(issues.isEmpty() ? CheckStatus.PASSED : CheckStatus.WARNING);
        
        return result;
    }
    
    /**
     * 检查证据清单格式
     */
    private void checkEvidenceListFormat(String content, List<String> issues) {
        if (!content.contains("序号") || !content.contains("证据名称")) {
            issues.add("证据清单缺少标准表格格式");
        }
        
        if (!content.contains("页数") && !content.contains("数量")) {
            issues.add("证据清单缺少页数或数量信息");
        }
    }
    
    /**
     * 检查证据编号
     */
    private void checkEvidenceNumbering(String content, List<String> issues) {
        Pattern numberPattern = Pattern.compile("\\d+[、．\\.]");
        Matcher matcher = numberPattern.matcher(content);
        
        List<Integer> numbers = new ArrayList<>();
        while (matcher.find()) {
            String numStr = matcher.group().replaceAll("[、．\\.]", "");
            try {
                numbers.add(Integer.parseInt(numStr));
            } catch (NumberFormatException e) {
                // 忽略解析错误
            }
        }
        
        // 检查编号连续性
        if (!numbers.isEmpty()) {
            Collections.sort(numbers);
            for (int i = 1; i < numbers.size(); i++) {
                if (numbers.get(i) != numbers.get(i-1) + 1) {
                    issues.add("证据编号不连续：" + numbers.get(i-1) + " 到 " + numbers.get(i));
                    break;
                }
            }
        }
    }
    
    /**
     * 检查证据描述
     */
    private void checkEvidenceDescription(String content, List<String> issues) {
        // 检查是否有空白的证据描述
        if (content.contains("证据名称") && content.contains("无") || content.contains("空白")) {
            issues.add("存在空白或无效的证据描述");
        }
    }
    
    /**
     * 通用增强检查
     */
    private EnhancedComplianceResult performGeneralEnhancedChecks(DocumentSegment document) {
        EnhancedComplianceResult result = new EnhancedComplianceResult();
        List<String> issues = new ArrayList<>();
        
        // 执行通用格式检查
        checkGeneralFormat(document, issues);
        
        result.setIssues(issues);
        result.setStatus(issues.isEmpty() ? CheckStatus.PASSED : CheckStatus.WARNING);
        
        return result;
    }
    
    /**
     * 通用格式检查
     */
    private void checkGeneralFormat(DocumentSegment document, List<String> issues) {
        String content = document.getFullText();
        
        // 检查基本要素
        if (!content.contains("日期") && !content.matches(".*\\d{4}年\\d{1,2}月\\d{1,2}日.*")) {
            issues.add("缺少日期信息");
        }
        
        // 检查机关名称
        String[] agencyKeywords = {"人民政府", "执法局", "监察局", "公安局"};
        boolean hasAgency = Arrays.stream(agencyKeywords)
                .anyMatch(content::contains);
        
        if (!hasAgency) {
            issues.add("缺少执法机关名称");
        }
    }
    
    /**
     * 合并检查结果
     */
    private void mergeResults(ComplianceResult baseResult, EnhancedComplianceResult enhancedResult) {
        if (!enhancedResult.getIssues().isEmpty()) {
            // 将增强检查的问题添加到基础结果中
            if (baseResult instanceof EnhancedComplianceResult) {
                ((EnhancedComplianceResult) baseResult).getIssues().addAll(enhancedResult.getIssues());
            }
            
            // 更新整体状态
            if (enhancedResult.getStatus() == CheckStatus.FAILED) {
                baseResult.setOverallStatus(CheckStatus.FAILED);
            } else if (enhancedResult.getStatus() == CheckStatus.WARNING && 
                       baseResult.getOverallStatus() == CheckStatus.PASSED) {
                baseResult.setOverallStatus(CheckStatus.WARNING);
            }
        }
    }
    
    /**
     * 初始化类型特定规则
     */
    private Map<DocumentType, ComplianceRuleSet> initializeTypeSpecificRules() {
        Map<DocumentType, ComplianceRuleSet> rules = new HashMap<>();
        
        // 处罚决定书规则
        ComplianceRuleSet decisionRules = new ComplianceRuleSet();
        decisionRules.setRequiredElements(Arrays.asList(getDecisionRequiredElements()));
        decisionRules.setStrictMode(true);
        rules.put(DocumentType.CASE_DECISION, decisionRules);
        
        // 告知书规则
        ComplianceRuleSet notificationRules = new ComplianceRuleSet();
        notificationRules.setRequiredElements(Arrays.asList("违法事实", "处罚依据", "陈述权", "申辩权"));
        notificationRules.setStrictMode(false);
        rules.put(DocumentType.NOTIFICATION, notificationRules);
        
        return rules;
    }
    
    /**
     * 增强型合规结果
     */
    public static class EnhancedComplianceResult extends ComplianceResult {
        private List<String> issues = new ArrayList<>();
        private CheckStatus status;
        
        public List<String> getIssues() { return issues; }
        public void setIssues(List<String> issues) { this.issues = issues; }
        
        public CheckStatus getStatus() { return status; }
        public void setStatus(CheckStatus status) { this.status = status; }
    }
    
    /**
     * 合规规则集
     */
    public static class ComplianceRuleSet {
        private List<String> requiredElements;
        private boolean strictMode;
        
        public List<String> getRequiredElements() { return requiredElements; }
        public void setRequiredElements(List<String> requiredElements) { this.requiredElements = requiredElements; }
        
        public boolean isStrictMode() { return strictMode; }
        public void setStrictMode(boolean strictMode) { this.strictMode = strictMode; }
    }
}